package com.citcc.business.service;

import com.citcc.business.bean.*;
import com.citcc.business.bean.dto.CdzAmountDetailCon;
import com.citcc.business.bean.vo.AmountDetailGetTypeVO;
import com.citcc.business.bean.vo.AmountDetailRecordVO;
import com.citcc.business.bean.vo.AmountDetailVO;
import com.citcc.business.mapper.*;
import com.citcc.common.jpush.PushUtil;
import com.citcc.common.utils.StringUtils;
import com.citcc.system.service.impl.SysDictDataServiceImpl;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by czh on 2019/5/17 14:53
 */
@Service
public class CdzAmountDetailService {
    private Logger logger = LoggerFactory.getLogger(CdzAmountDetailService.class);

    @Autowired
    private CdzAmountDetailMapper amountDetailMapper;
    @Autowired
    private CdzAccountAmountMapper accountAmountMapper;
    @Autowired
    private UserOrderEntityMapper userOrderEntityMapper;
    @Autowired
    private CdzStakeMapper cdzStakeMapper;
    @Autowired
    private CdzStationMapper cdzStationMapper;
    @Autowired
    private CdzRatesMapper cdzRatesMapper;
    @Autowired
    private CdzAppUserMapper cdzAppUserMapper;
    @Autowired
    private CdzPushMapper cdzPushMapper;
    @Autowired
    private SysDictDataServiceImpl sysDictDataService;

    private static final DecimalFormat FORMAT = new DecimalFormat("#,##0.00");

    /**
     * 查询冻结记录
     *
     * @param con
     * @return
     */
    public List<CdzAmountDetail> getFreezeAll(CdzAmountDetailCon con) {
        return amountDetailMapper.getFreezeAll(con);
    }

    /**
     * 余额明细
     *
     * @param userId
     * @return
     */
    public AmountDetailVO rechargeRecord(String userId, String type) {

        AmountDetailVO amountDetailVO = new AmountDetailVO();
        List<AmountDetailRecordVO> amountDetailRecordVOList;
        // 获取全部余额明细
        if (StringUtils.equals("0", type)) {
            amountDetailRecordVOList = amountDetailMapper.selectByUserIdAndType(userId, null);
        } else {
            // 根据操作类型获取相应的余额明细
            amountDetailRecordVOList = amountDetailMapper.selectByUserIdAndType(userId, type);
        }

        amountDetailVO.setTotalSize(new PageInfo(amountDetailRecordVOList).getTotal());
        Optional.ofNullable(amountDetailRecordVOList).ifPresent(result -> amountDetailVO.setDetailList(result.stream().map(s -> {
            AmountDetailRecordVO amountDetailRecordVO = new AmountDetailRecordVO();
            Integer typeState = s.getTypeState();
            amountDetailRecordVO.setTypeState(typeState);
            switch (typeState) {
                case 1:
                case 3:
                    amountDetailRecordVO.setTypeDesc(s.getPayType() + s.getTypeDesc());
                    amountDetailRecordVO.setAmount(FORMAT.format(new BigDecimal(s.getAmount())));
                    break;
                case 2:
                    amountDetailRecordVO.setTypeDesc(s.getStationName() + s.getTypeDesc());
                    amountDetailRecordVO.setAmount(FORMAT.format(new BigDecimal(s.getAmount()).subtract(new BigDecimal(s.getOffMoney()))));
                    break;
                default:
                    amountDetailRecordVO.setTypeDesc(s.getTypeDesc());
                    amountDetailRecordVO.setAmount(FORMAT.format(new BigDecimal(s.getAmount())));
            }
            amountDetailRecordVO.setMoneyFlag(s.getMoneyFlag());
            amountDetailRecordVO.setCreateTime(s.getCreateTime());
            amountDetailRecordVO.setPayType(s.getPayType());
            amountDetailRecordVO.setPayState(s.getPayState());
            amountDetailRecordVO.setStationName(s.getStationName());
            return amountDetailRecordVO;
        }).sorted(Comparator.comparing(AmountDetailRecordVO::getCreateTime).reversed()).collect(Collectors.toList())));

        return amountDetailVO;
    }

    /**
     * 余额明细操作类型
     *
     * @return
     */
    public List<AmountDetailGetTypeVO> getType() {

        List<AmountDetailGetTypeVO> amountDetailTypeList = new ArrayList<>();
        amountDetailTypeList.add(new AmountDetailGetTypeVO(0, "全部", 0L));

        Optional.ofNullable(sysDictDataService.selectDictDataByType("acc_oper_type")).ifPresent(result -> amountDetailTypeList.addAll(result.stream().map(s -> {
            AmountDetailGetTypeVO amountDetailType = new AmountDetailGetTypeVO();
            amountDetailType.setTypeState(Integer.valueOf(s.getDictValue()));
            amountDetailType.setTypeDesc(s.getDictLabel());
            amountDetailType.setOrderBy(s.getDictSort());
            return amountDetailType;
        }).filter(o -> o.getTypeState() != 4).sorted(Comparator.comparing(AmountDetailGetTypeVO::getOrderBy)).collect(Collectors.toList())));

        return amountDetailTypeList;
    }

    /**
     * 插入数据
     *
     * @param cdzAmountDetail
     * @return
     */
    @Transactional
    public int save(CdzAmountDetail cdzAmountDetail) {
        return amountDetailMapper.insertSelective(cdzAmountDetail);
    }

    /**
     * 结束充电成功后业务逻辑
     *
     * @param id 订单id
     */
    @Transactional
    public void endChargeBusiness(String id) {
        logger.info("endChargeBusiness_id:" + id);
        UserOrderEntity order = userOrderEntityMapper.selectByPrimaryKey(id);
        //充电电量
        String chargeDn = order.getChargeDn();
        String money = "0";
        //根据桩号查询站号，站号拿到rates值，查询费率
        CdzStake cdzStake = cdzStakeMapper.getByStakeCode(order.getStakeCode());
        CdzStation cdzStation = cdzStationMapper.selectByPrimaryKey(cdzStake.getStationId());
        //1:直流 2:交流 3:混合
        String type = cdzStation.getType();
        BigDecimal serve = new BigDecimal(0);
        String rates = cdzStation.getRates();
        CdzRates cdzRates = cdzRatesMapper.selectByPrimaryKey(rates);
        //根据用户id查询客户类型（0普通客户1内部客户）
        CdzAppUser user = cdzAppUserMapper.selectByPrimaryKey(order.getUserId());
        switch (type) {
            case "1":
                //直流充电
                //服务费
                serve = cdzRates.getServe();
                //算内部用户优惠价格
                if ("1".equals(user.getUserType())) {
                    BigDecimal electricity = new BigDecimal(chargeDn);
                    //优惠金额= 已充电量*服务费
                    Double amount = electricity.multiply(serve).doubleValue();
                    money = amount.toString();
                }
                break;
            case "2":
                //服务费
                serve = cdzRates.getServe();
                //算内部用户优惠价格
                if ("1".equals(user.getUserType())) {
                    BigDecimal electricity = new BigDecimal(chargeDn);
                    //优惠金额= 已充电量*服务费
                    Double amount = electricity.multiply(serve).doubleValue();
                    money = amount.toString();
                }
                break;
            default:
                money = "0";
                break;
        }
        UserOrderEntity userOrderEntity = new UserOrderEntity();
        //如果是内部客户是优惠金额，如果是普通客户优惠金额是0
        BigDecimal payAmount = new BigDecimal(money);
        //实付金额
        BigDecimal amount = new BigDecimal(0);
        if ("1".equals(user.getUserType())) {//内部价格
            //实付金额 = 充电费用(实际充电金额) -优惠金额
            double doubleValue = order.getPayNumberPlan().subtract(payAmount).doubleValue();
            //设值优惠金额
            userOrderEntity.setOffMoney(payAmount);
            userOrderEntity.setOffType("内部价格");
            //将算好的实付金额赋值给amount
            amount = new BigDecimal(doubleValue);
        } else {
            //硬件算好的实付金额
            amount = order.getPayNumberPlan();
        }
        userOrderEntity.setMoney(amount);
        //更新订单
        userOrderEntity.setId(id);
        //支付状态（0：未冻结，1：已冻结 2：成功 3：失败）
        userOrderEntity.setPayState("2");
        //获取时间
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.now();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        Date date = Date.from(zdt.toInstant());
        userOrderEntity.setPayTime(date);
        userOrderEntity.setPayType("3");
        userOrderEntityMapper.updateByPrimaryKeySelective(userOrderEntity);

        //插入充电记录数据
        CdzAmountDetail cdzAmountDetail = new CdzAmountDetail();
        cdzAmountDetail.setUserId(order.getUserId());
        cdzAmountDetail.setType("2");
        //充电金额
        cdzAmountDetail.setAmount(order.getPayNumberPlan());
        //优惠金额
        cdzAmountDetail.setOffMoney(payAmount);
        //充电之前总金额
        CdzAccountAmount accountAmount = accountAmountMapper.selectByUserId(order.getUserId());
        cdzAmountDetail.setBeforeAmount(accountAmount.getTotalAmount());
        //充电之后总金额=充电之前总金额-充电金额
        cdzAmountDetail.setAfterAmount(accountAmount.getTotalAmount().subtract(amount));
        cdzAmountDetail.setStationName(order.getStationName());
        cdzAmountDetail.setOrderId(id);
        amountDetailMapper.insertSelective(cdzAmountDetail);

        //修改冻结记录
        //金额明细表
        CdzAmountDetail cdzAmountDetail1 = amountDetailMapper.selectByFreeze(order.getUserId());
        cdzAmountDetail1.setInvalidFlag("1");
        cdzAmountDetail1.setInvalidTime(date);
        amountDetailMapper.updateByPrimaryKeySelective(cdzAmountDetail1);

        //账户金额表
        CdzAccountAmount cdzAccountAmount = new CdzAccountAmount();
        cdzAccountAmount.setId(accountAmount.getId());
        cdzAccountAmount.setFrozenFlag("0");
        //可用金额=总金额-实付金额
        BigDecimal bd = accountAmount.getTotalAmount().subtract(amount);
        cdzAccountAmount.setAvailableAmount(bd);
        cdzAccountAmount.setTotalAmount(bd);
        //冻结金额设为0
        BigDecimal frozenAmount = new BigDecimal(0);
        cdzAccountAmount.setFrozenAmount(frozenAmount);
        accountAmountMapper.updateByPrimaryKeySelective(cdzAccountAmount);

        //所有业务逻辑走完后，推送通知到app，并且插入推送历史表
        List<Object> registrationIdList = new ArrayList<>();
        if (StringUtils.isNotEmpty(user.getDeviceId())) {
            registrationIdList.add(user.getDeviceId());
            String title = "充电订单已完成";
            String body = "您的充电订单已完成，点击查看详情。";
            String url = "/h5/chargingPile/orderDetail.html?id=" + id;
            try {
                PushUtil.msgPush(registrationIdList, title, body, "1", url, user.getType());
            } catch (Exception e) {
                e.printStackTrace();
            }
            //插入推送数据
            CdzPush push = new CdzPush();
            push.setTitle(title);
            push.setContent(body);
            push.setUrl(url);
            push.setUserId(user.getId());
            push.setPushTime(date);
            cdzPushMapper.insertSelective(push);
        }
    }


    /**
     * 开启充电成功后业务逻辑
     *
     * @param cdOrder
     */
    @Transactional
    public void startChargeBusiness(UserOrderEntity cdOrder) {
        //操作之前总金额
        CdzAccountAmount accountAmount = accountAmountMapper.selectByUserId(cdOrder.getUserId());
        //如果是未冻结标记，插入逻辑。
        if (null != accountAmount && "0".equals(accountAmount.getFrozenFlag())) {
            //开始插入金额明细表，冻结记录数据
            CdzAmountDetail cdzAmountDetail = new CdzAmountDetail();
            cdzAmountDetail.setUserId(cdOrder.getUserId());
            cdzAmountDetail.setType("4");
            //操作金额
            cdzAmountDetail.setAmount(cdOrder.getPayNumber());

            cdzAmountDetail.setBeforeAmount(accountAmount.getTotalAmount());
            //操作之后总金额=操作之前总金额-操作金额
            double value = accountAmount.getTotalAmount().subtract(cdOrder.getPayNumber()).doubleValue();
            BigDecimal afterAmount = new BigDecimal(value);
            cdzAmountDetail.setAfterAmount(afterAmount);
            cdzAmountDetail.setInvalidFlag("0");
            cdzAmountDetail.setOrderId(cdOrder.getId());
            amountDetailMapper.insertSelective(cdzAmountDetail);

            //更新金额数据
            CdzAccountAmount cdzAccountAmount = new CdzAccountAmount();
            cdzAccountAmount.setUserId(cdOrder.getUserId());
            cdzAccountAmount.setFrozenAmount(cdOrder.getPayNumber());
            cdzAccountAmount.setFrozenFlag("1");
            cdzAccountAmount.setAvailableAmount(afterAmount);
            accountAmountMapper.updateByUserIdSelective(cdzAccountAmount);

            UserOrderEntity userOrderEntity = new UserOrderEntity();
            userOrderEntity.setId(cdOrder.getId());
            // 支付状态（0：未冻结，1：已冻结 2：成功 3：失败）
            userOrderEntity.setPayState("1");
            userOrderEntityMapper.updateByPrimaryKeySelective(userOrderEntity);
        }
    }


    /**
     * 删除记录
     */
    public int delete(String id) {
        return amountDetailMapper.deleteByPrimaryKey(id);
    }

}